package zelix;

import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.client.renderer.entity.layers.LayerCape;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import zelix.eventapi.EventManager;
import zelix.eventapi.event.EventPlayerPost;
import zelix.eventapi.event.EventPlayerPre;
import zelix.hack.Hack;
import zelix.hack.hacks.ClickGui;
import zelix.eventapi.EventTarget;
import zelix.managers.CapeManager;
import zelix.managers.FileManager;
import net.minecraftforge.client.event.*;
import org.lwjgl.input.Keyboard;
import net.minecraftforge.event.entity.ProjectileImpactEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import zelix.gui.clickguis.gishcode.ClickGuiScreen;
import zelix.hack.hacks.AntiBot;
import zelix.hack.hacks.GhostMode;
import zelix.managers.HackManager;
import zelix.utils.ReflectionHelper;
import zelix.utils.Utils;
import zelix.utils.cape.CustomLayerCape;
import zelix.utils.system.Connection;
import zelix.utils.Wrapper;

import java.lang.reflect.Field;
import java.util.*;

public class EventsHandler {
	private boolean initialized = false;

	public EventsHandler(){
		EventManager.register(this);
	}

	public boolean onPacket(Object packet, Connection.Side side) {
        boolean suc = true;
        for (Hack hack : HackManager.getHacks()) {
            if (!hack.isToggled() || Wrapper.INSTANCE.world() == null) {
                continue;
            }
            suc &= hack.onPacket(packet, side);
        }
        return suc;
    }
	
	@SubscribeEvent
    public void onGuiContainer(GuiContainerEvent event) {
		if(Utils.nullCheck()) return;
    	try {
    		HackManager.onGuiContainer(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onGuiContainer");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}

	@SubscribeEvent
	public void onRender3D(RenderBlockOverlayEvent event) {
		if (Utils.nullCheck() || Wrapper.INSTANCE.mcSettings().hideGUI)
			return;
		try {
			HackManager.onRender3D(event);
		} catch (RuntimeException ex) {
			ex.printStackTrace();
			//ChatUtils.error("RuntimeException: onRenderWorldLast");
			//ChatUtils.error(ex.toString())
			//Utils.copy(ex.toString());
		}
	}

	@SubscribeEvent
    public void onGuiOpen(GuiOpenEvent event) {
		if(Utils.nullCheck()) return;
    	try {
			FileManager.saveHacks();
    		HackManager.onGuiOpen(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onGuiOpen");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	
	@SubscribeEvent
    public void onMouse(MouseEvent event) {
		if(Utils.nullCheck()) return;
    	try {
    		HackManager.onMouse(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onMouse");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	
	@SubscribeEvent
    public void onKeyInput(InputEvent.KeyInputEvent event) {
		if(Utils.nullCheck()) return;
    	try {
    		int key = Keyboard.getEventKey();
			if (key == 0 || key == -1){
				return;
			}
    		if(Keyboard.getEventKeyState()) {
    			HackManager.onKeyPressed(key);
    		}
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onKeyInput");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	
	
	@SubscribeEvent
    public void onCameraSetup(EntityViewRenderEvent.CameraSetup event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onCameraSetup(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onCameraSetup");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	
	@SubscribeEvent
    public void onItemPickup(EntityItemPickupEvent event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onItemPickup(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onItemPickup");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
    } 
	
	@SubscribeEvent
    public void onProjectileImpact(ProjectileImpactEvent event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onProjectileImpact(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: ProjectileImpact");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
    	
	
    @SubscribeEvent
    public void onAttackEntity(AttackEntityEvent event) {
    	if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onAttackEntity(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onAttackEntity");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
    }    
    
    @SubscribeEvent
    public void onPlayerTick(TickEvent.PlayerTickEvent event) {
    	if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onPlayerTick(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onPlayerTick");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
    }

	//private static final Field FIELD_RENDERERS =  ReflectionHelper.findField((Class) RenderLivingBase.class, new String[] { "layerRenderers", "field_177097_h" });
	//private final ArrayList<LayerRenderer> oldCapes;
	private boolean flag;
	private boolean flag1;
	public String map = "";
	@SubscribeEvent(receiveCanceled = true)
	public void onRenderPlayer(final RenderPlayerEvent.Pre event) {
		if (event.getEntity() != null){
			if (!map.contains(event.getEntity().getName()+";")){
				event.getRenderer().addLayer((LayerRenderer)new CustomLayerCape(event.getRenderer()));
				map = map + event.getEntity().getName()+";";
			}
		}
	}

	public WorldClient upworld = null;
    @SubscribeEvent
    public void onClientTick(TickEvent.ClientTickEvent event) {
    	//Display.setTitle(Get.get("https://v1.hitokoto.cn/?c=a&encode=text").toString());
    	
    	if(Utils.nullCheck()) {
    		AntiBot.bots.clear();
    		initialized = false;
    		return; 
    	}
    	try {
    		if (!initialized) {
                new Connection(this);
                ClickGui.setColor();
                initialized = true;
            }
			if (Minecraft.getMinecraft().world.equals(upworld)){

			}else{
				upworld = Minecraft.getMinecraft().world;


				map =  "";
			}
			//com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService


    		if(!(Wrapper.INSTANCE.mc().currentScreen instanceof ClickGuiScreen))
    			HackManager.getHack("ClickGui").setToggled(false);
    		if(!GhostMode.enabled)
    			HackManager.onClientTick(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onClientTick");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
    }
    
    @SubscribeEvent
    public void onLivingUpdate(LivingEvent.LivingUpdateEvent event) {
    	if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onLivingUpdate(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onLivingUpdate");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
    }
    
    @SubscribeEvent
    public void onRenderWorldLast(RenderWorldLastEvent event) {
    	if(Utils.nullCheck() || GhostMode.enabled || Wrapper.INSTANCE.mcSettings().hideGUI) return;
    	try {
    		HackManager.onRenderWorldLast(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onRenderWorldLast");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
    }
	
	@SubscribeEvent
    public void onRenderGameOverlay(RenderGameOverlayEvent.Text event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onRenderGameOverlay(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onRenderGameOverlay");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	
	@SubscribeEvent
	public void onLeftClickBlock(PlayerInteractEvent.LeftClickBlock event){
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onLeftClickBlock(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onPlayerDamageBlock");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	@SubscribeEvent
	public void onInputUpdateEvent(InputUpdateEvent event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onInputUpdate(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onPlayerDamageBlock");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	@EventTarget
	public void onPlayerEventPre(EventPlayerPre event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onPlayerEventPre(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onPlayerEventPre");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
	@EventTarget
	public void onPlayerEventPost(EventPlayerPost event) {
		if(Utils.nullCheck() || GhostMode.enabled) return;
    	try {
    		HackManager.onPlayerEventPost(event);
    	} catch (RuntimeException ex) {
    		ex.printStackTrace();
    		//ChatUtils.error("RuntimeException: onPlayerEventPost");
    		//ChatUtils.error(ex.toString())
    		//Utils.copy(ex.toString());
    	}
	}
}
